using Microsoft.Extensions.DependencyInjection;

namespace YMJake.Flowable.ExternalWorker.Client.AspNetCore.Pipeline;

/// <summary>
/// Implementation of Flowable worker builder
/// </summary>
public class FlowableWorkerBuilder : IFlowableWorkerBuilder
{
    private readonly WorkerPipeline _pipeline = new();
    public IServiceCollection Services { get; }
    public string Topic { get; }
    public int Concurrency { get; private set; } = 1;
    public TimeSpan PollingInterval { get; private set; } = TimeSpan.FromSeconds(30);
    public TimeSpan LockDuration { get; private set; } = TimeSpan.FromMinutes(1);

    public FlowableWorkerBuilder(IServiceCollection services, string topic)
    {
        Services = services ?? throw new ArgumentNullException(nameof(services));
        Topic = topic ?? throw new ArgumentNullException(nameof(topic));
    }

    public IFlowableWorkerBuilder AddHandler<THandler>() where THandler : class, IWorkerHandler
    {
        // 自动注册处理器服务到DI容器（学习camunda的做法）
        Services.AddScoped<THandler>();
        _pipeline.AddHandler<THandler>();
        return this;
    }



    public IFlowableWorkerBuilder ConfigurePipeline(Action<IWorkerPipeline> configure)
    {
        configure.Invoke(_pipeline);
        return this;
    }

    public IFlowableWorkerBuilder WithConcurrency(int concurrency)
    {
        if (concurrency <= 0)
            throw new ArgumentOutOfRangeException(nameof(concurrency), "Concurrency must be greater than 0");
        
        Concurrency = concurrency;
        return this;
    }

    public IFlowableWorkerBuilder WithPollingInterval(TimeSpan interval)
    {
        if (interval <= TimeSpan.Zero)
            throw new ArgumentOutOfRangeException(nameof(interval), "Polling interval must be greater than zero");
        
        PollingInterval = interval;
        return this;
    }

    public IFlowableWorkerBuilder WithLockDuration(TimeSpan duration)
    {
        if (duration <= TimeSpan.Zero)
            throw new ArgumentOutOfRangeException(nameof(duration), "Lock duration must be greater than zero");
        
        LockDuration = duration;
        return this;
    }

    /// <summary>
    /// Build the pipeline for this worker
    /// </summary>
    internal WorkerMiddleware BuildPipeline()
    {
        return _pipeline.Build();
    }
}